/*******************************************************************************
*  file    : windvidget.cpp
*  created : 11.07.2014
*  author  : Slyshyk Oleksiy (alexSlyshyk@gmail.com)
*******************************************************************************/

#include "windwidget.hpp"
#include "ui_windwidget.h"
#include <QFileDialog>
#include <QBoxLayout>
#include <QDateTime>
#include <QTimer>

#include "solutions.hpp"
#include <boost/range.hpp>
#include <boost/range/algorithm.hpp>

namespace rng = boost::range ;

#include <qwt_plot_curve.h>
#include <qwt_symbol.h>
#include <qwt_scale_draw.h>
#include <qwt_legend.h>
#include <qwt_legend_label.h>
#include <qwtchartzoom.h>

class TimeScaleDraw: public QwtScaleDraw
{
public:
    virtual QwtText label( double v ) const
    {
        QDateTime upTime;
        upTime.setMSecsSinceEpoch(static_cast<qint64>(v));
        return upTime.toString("mm:ss");
    }
};

WindWidget::WindWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::WindWidget)
{
    ui->setupUi(this);

    plot_ = new QwtPlot;
    legend_ = new QwtLegend;
    plot_->insertLegend( legend_, QwtPlot::TopLegend );
    // Делаем легенды кликабельными
    legend_->setDefaultItemMode( QwtLegendData::Checkable );
    connect( legend_, SIGNAL( checked(QVariant,bool,int)) ,
        SLOT( showCurve(QVariant,bool,int) ) );

    curves_["wind_speed_filtered"].reset(new QwtPlotCurve);
    curves_["wind_speed_filtered"]->attach(plot_);
    curves_["wind_speed_filtered"]->setPen( QPen( QColor( "blue" ), 2 ) );
    QwtSymbol * symb = new QwtSymbol(QwtSymbol::Diamond);
    symb->setSize(5);
    symb->setColor(curves_["wind_speed_filtered"]->pen().color().darker());
    curves_["wind_speed_filtered"]->setSymbol(symb);
    showCurve(plot_->itemToInfo(curves_["wind_speed_filtered"].data()), true);

    curves_["wind_speed"].reset(new QwtPlotCurve);
    curves_["wind_speed"]->attach(plot_);
    curves_["wind_speed"]->setPen( QPen( QColor( "blue" ).darker(), 2 ) );
    symb = new QwtSymbol(QwtSymbol::VLine);
    symb->setSize(5);
    symb->setColor(curves_["wind_speed"]->pen().color().darker());
    curves_["wind_speed"]->setSymbol(symb);
    showCurve(plot_->itemToInfo(curves_["wind_speed"].data()), true);

    curves_["wind_speed_ma"].reset(new QwtPlotCurve);
    curves_["wind_speed_ma"]->attach(plot_);
    curves_["wind_speed_ma"]->setPen( QPen( QColor( "yellowgreen" ), 2 ) );
    symb = new QwtSymbol(QwtSymbol::VLine);
    symb->setSize(5);
    symb->setColor(curves_["wind_speed_ma"]->pen().color().darker());
    curves_["wind_speed_ma"]->setSymbol(symb);
    showCurve(plot_->itemToInfo(curves_["wind_speed_ma"].data()), true);

    curves_["wind_speed_ma2"].reset(new QwtPlotCurve);
    curves_["wind_speed_ma2"]->attach(plot_);
    curves_["wind_speed_ma2"]->setPen( QPen( QColor( "yellowgreen" ).darker(), 2 ) );
    symb = new QwtSymbol(QwtSymbol::VLine);
    symb->setSize(5);
    symb->setColor(curves_["wind_speed_ma2"]->pen().color().darker());
    curves_["wind_speed_ma2"]->setSymbol(symb);
    showCurve(plot_->itemToInfo(curves_["wind_speed_ma2"].data()), true);

    curves_["temperature"].reset(new QwtPlotCurve);
    curves_["temperature"]->attach(plot_);
    curves_["temperature"]->setPen( QPen( QColor( "red" ), 2 ) );
    symb = new QwtSymbol(QwtSymbol::VLine);
    symb->setSize(5);
    symb->setColor(curves_["temperature"]->pen().color().darker());
    curves_["temperature"]->setSymbol(symb);
    showCurve(plot_->itemToInfo(curves_["temperature"].data()), true);

    curves_["pressure"].reset(new QwtPlotCurve);
    curves_["pressure"]->attach(plot_);
    curves_["pressure"]->setPen( QPen( QColor( "yellow" ).darker(), 2 ) );
    symb = new QwtSymbol(QwtSymbol::VLine);
    symb->setSize(5);
    symb->setColor(curves_["pressure"]->pen().color().darker());
    curves_["pressure"]->setSymbol(symb);
    showCurve(plot_->itemToInfo(curves_["pressure"].data()), true);

    //zoom_ = new QwtChartZoom(plot_, this);
    //zoom_->setRubberBandColor(Qt::red);

    plot_->setMinimumSize(200,100);
    plot_->setAxisScaleDraw(QwtPlot::xBottom, new TimeScaleDraw);
    plot_->setAxisLabelRotation( QwtPlot::xBottom, -50.0 );
    wind_points_.set_capacity(25);

    ui->windGroupBox->setLayout(new QHBoxLayout);
    ui->windGroupBox->layout()->addWidget(plot_);

    connect(ui->openDirButon, &QPushButton::clicked, this, &WindWidget::openDir );
    connect(ui->time_L_SpinBox, SIGNAL(valueChanged(double)), this, SIGNAL(responceTimeChanged()) );
    connect(ui->time_R_SpinBox, SIGNAL(valueChanged(double)), this, SIGNAL(responceTimeChanged()) );
}

WindWidget::~WindWidget()
{
    delete ui;
}

void WindWidget::setResponceTime(double t_l, double t_r)
{
    ui->time_L_SpinBox->setValue(t_l);
    ui->time_R_SpinBox->setValue(t_r);
}

double WindWidget::responceTimeR() const
{
    return ui->time_L_SpinBox->value();
}

double WindWidget::responceTimeL() const
{
    return ui->time_L_SpinBox->value();
}

double WindWidget::temperature() const
{
    return ui->temperatureSpinBox->value();
}

void WindWidget::setTemperature(double t)
{
    ui->temperatureSpinBox->setValue(t);
}

QString WindWidget::path() const
{
    return ui->lineEdit->text();
}

void WindWidget::setSolutions(Solutions *sln)
{
    solutions_ = sln;
    if( solutions_ )
        QTimer::singleShot(500, this, SLOT(updateWindSpeedPlot()) );
}

void WindWidget::changeEvent(QEvent *e)
{
    QWidget::changeEvent(e);
    switch (e->type()) {
        case QEvent::LanguageChange:
            ui->retranslateUi(this);
            break;
        default:
            break;
        }
}

void WindWidget::openDir()
{
    static QString last_opened = QStringLiteral(".");
    auto dir_name = QFileDialog::getExistingDirectory(this, QStringLiteral("Выбор директории."),last_opened);
    if(dir_name.size())
        {
            last_opened = dir_name;
            ui->lineEdit->setText(last_opened);
            emit pathChanged(last_opened);
        }
}

void WindWidget::updateWindSpeedPlot()
{
    if( solutions_ )
        {
            auto sort_series = [](QVector<QPointF>& s){rng::sort(s,[](const QPointF& p1,const QPointF& p2){return (p1.x() < p2.x());}) ;};

            QVector<QPointF> series;
            series.resize(solutions_->speeds().size());
            for(decltype(series.size()) i = 0; i < series.size(); ++i)
                series[i] = QPointF(solutions_->speeds().at(i).first,solutions_->speeds().at(i).second);
            sort_series(series);
            curves_["wind_speed_filtered"]->setSamples(series);

            if(series.size())
                ui->lcdNumber->setText(QString::number(series.back().y(),'f',10));


            series.resize(solutions_->ma_speeds().size());
            for(decltype(series.size()) i = 0; i < series.size(); ++i)
                series[i] = QPointF(solutions_->ma_speeds().at(i).first,solutions_->ma_speeds().at(i).second);
            sort_series(series);
            curves_["wind_speed_ma"]->setSamples(series);

            series.resize(solutions_->ma2_speeds().size());
            for(decltype(series.size()) i = 0; i < series.size(); ++i)
                series[i] = QPointF(solutions_->ma2_speeds().at(i).first,solutions_->ma2_speeds().at(i).second);
            sort_series(series);
            curves_["wind_speed_ma2"]->setSamples(series);


            series.resize(solutions_->solutions().size());
            for(decltype(solutions_->solutions().size()) i = 0; i < solutions_->solutions().size(); ++i)
                series[i] = QPointF(solutions_->solutions().at(i).time, solutions_->solutions().at(i).delta_V);
            sort_series(series);
            curves_["wind_speed"]->setSamples(series);

            series.resize(solutions_->solutions().size());
            for(decltype(solutions_->solutions().size()) i = 0; i < solutions_->solutions().size(); ++i)
                series[i] = QPointF(solutions_->solutions().at(i).time, solutions_->solutions().at(i).pressure/10000.0);
            sort_series(series);
            curves_["pressure"]->setSamples(series);

            series.resize(solutions_->solutions().size());
            for(decltype(solutions_->solutions().size()) i = 0; i < solutions_->solutions().size(); ++i)
                series[i] = QPointF(solutions_->solutions().at(i).time, solutions_->solutions().at(i).temperature /100.0);
            sort_series(series);
            curves_["temperature"]->setSamples(series);

            plot_->replot();
        }

    QTimer::singleShot(500, this, SLOT(updateWindSpeedPlot()) );
}

void WindWidget::showCurve(const QVariant &itemInfo, bool on, int index)
{
    QwtPlotItem *plotItem = plot_->infoToItem( itemInfo );

    if ( plotItem->rtti() == QwtPlotItem::Rtti_PlotCurve )
        {
            QwtPlotCurve *curve = static_cast<QwtPlotCurve *>( plotItem );
            curve->setVisible(on);

            QwtLegend *lgd = qobject_cast<QwtLegend *>( plot_->legend() );

            QList<QWidget *> legendWidgets =
                lgd->legendWidgets( plot_->itemToInfo( curve ) );

            if ( legendWidgets.size() == 1 )
                {
                    QwtLegendLabel *legendLabel =
                        qobject_cast<QwtLegendLabel *>( legendWidgets[0] );

                    if ( legendLabel )
                        legendLabel->setChecked( on );
                }
        }

    plot_->replot();

    Q_UNUSED(index)
}

void WindWidget::setPath(const QString &path)
{
    ui->lineEdit->setText(path);
    emit pathChanged(path);
}

void WindWidget::setWindSpeed(qint64 t, double s)
{
    qDebug() << QString("--------------  --------- RECV time %1").arg(t);
    ui->lcdNumber->setText(QString::number(s,'f',10));
    wind_points_.push_back( std::make_pair(t , s) );
    rng::sort(wind_points_,[](const std::pair<qint64,double>& p1, const std::pair<qint64,double>& p2)->bool{return (p1.first < p2.first);});
    QVector<QPointF> series;
    series.resize(wind_points_.size());
    for(decltype(wind_points_.size()) i = 0; i < wind_points_.size(); ++i)
        series[i] = QPointF(wind_points_[i].first,wind_points_[i].second);
    curves_["wind_speed_filtered"]->setSamples(series);
    plot_->replot();
}
